
#include "LPC23xx.h" 
#include "App.h" 
#include "OS.h" 
#include "app_menu.h" 
#include "debug.h" 
#include "dtmf.h" 
#include "macros.h" 
#include "SysClock.h" 
#include "menu_msg.h" 
#include "isd.h" 
#include "modem.h" 
#include "storage.h" 
#include "entrys.h" 
//#include "receivers.h" 
#include "string.h" 
#include "outp.h" 
#include "memmap.h" 
#include "Config.h" 
#include "utils.h" 
#include "apps.h" 

#define   OUTPUT_TIMEOUT		(AA_Config.time_unit*AA_Config.output_timeout)


typedef struct _audio_menu_t
{
		exe *menu_handler;
		int *menu_msg;
		int menu_item;
		struct _audio_menu_t *menu_back;
		
}audio_menu_t;

audio_menu_t audio_menu_ChangeOutputs;
audio_menu_t audio_menu_ChangeOutput_1;
audio_menu_t audio_menu_ChangeOutput_2;
audio_menu_t audio_menu_ChangeOutput_3;
audio_menu_t audio_menu_Config;

audio_menu_t audio_menu_Config_ChangeOutputTimeout;
audio_menu_t audio_menu_Config_ChangeOutputTimeout_Unit;
audio_menu_t audio_menu_Config_ChangeOutputTimeout_Timeout;
audio_menu_t audio_menu_Config_ChangeOutputsName;


audio_menu_t audio_menu_Welcome;
audio_menu_t *audio_menu;

void menu_play ( void );
void menu_play ( void )
{	
	if ( APP.Signal == APP_SIGNAL_CLOSE )
	{
		DBG("\n%s; APP_SIGNAL_CLOSE\n",__FUNCTION__); 
		APP.State = ASTE_FINISH;
	}

	switch(APP.State)
	{
		case ASTE_START:
			DBG("\n%s; = PLAY MENU =\n",__FUNCTION__); 
			OS_SET_TIMER(20000, ASTE_FINISH);
			if ( audio_menu->menu_msg )
			{
				msg_play__msgs = audio_menu->menu_msg;
				APP.State = ASTE_PLAY_MSG; 
			}
			else
			{
				DBG("\n%s; ====>> audio_menu->menu_msg == NULL !!!!\n",__FUNCTION__); 
				APP.State = ASTE_FINISH;
				break;
			}

		case ASTE_PLAY_MSG:
			if ( APP.CallResult ) msg_play__msgs++; 
			if ( *msg_play__msgs != AMSG_END_OF_MSG )
			{
				msg_play__msg = *msg_play__msgs; 
				OS_Call_App(1,msg_play);
			}
			else
			{
				APP.State = ASTE_FINISH;
			}
			break;

		case ASTE_FINISH:
			msg_play__msgs = NULL;
			am_stop_msg();
			DBG("\n%s; FINISH\n",__FUNCTION__); 
			OS_Return();

	}  

}

unsigned int OutName, OutName_2, OutName_3;

static void menu_handler_ChangeOutputs ( void )
{
	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			OutName = OUT_RELAY_1;
			OutName_2 = OUT_RELAY_1A;
			OutName_3 = OUT_LED_1;
			audio_menu = &audio_menu_ChangeOutput_1;
			break;

		case MH_ITEM_2:
			OutName = OUT_RELAY_2;
			OutName_2 = OUT_RELAY_2A;
			OutName_3 = OUT_LED_2;
			audio_menu = &audio_menu_ChangeOutput_2;
			break;

		case MH_ITEM_3:
			OutName = OUT_RELAY_3;
			OutName_2 = OUT_RELAY_3A;
			OutName_3 = OUT_LED_3;
			audio_menu = &audio_menu_ChangeOutput_3;
			break;

		case MH_ITEM_4:
			audio_menu = &audio_menu_Config;
			break;

		default:
			;
			
	} 

	APP.Result = AR_PLAY_MENU;

	DBG("\n%s; audio_menu_ChangeOutputs.menu_item: %d\n",__FUNCTION__, audio_menu_Welcome.menu_item); 
	
	OS_Return();
}


static void menu_handler_ChangeOutput ( void )
{
	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			if ( OUTP_READ(OutName) )
			{
				DBG("\n%s; OutName: %d; == HIGH ==\n",__FUNCTION__,OutName); 
				OUTP_RESET(OutName);
				OUTP_RESET(OutName_2);
				OUTP_SET(OutName_3, 0);
				audio_menu->menu_msg[1] = AMSG_OUTPUT_STATE_OFF;
			}
			else
			{
				DBG("\n%s; OutName: %d; == LOW ==\n",__FUNCTION__,OutName); 
				OUTP_SET(OutName, OUTPUT_TIMEOUT);
				OUTP_SET(OutName_2, OUTPUT_TIMEOUT);
				//OUTP_RESET(OutName_3);
				OutSet(OutName_3,~0x3ff,OUTPUT_TIMEOUT*100, 11);
				audio_menu->menu_msg[1] = AMSG_OUTPUT_STATE_ON;
			}
			APP.Result = AR_PLAY_MENU;
			break;

		default:
			audio_menu = audio_menu->menu_back;
			APP.Result = AR_PLAY_MENU;
	} 

	DBG("\n%s; audio_menu_ChangeOutput.menu_item: %d\n",__FUNCTION__, audio_menu_Welcome.menu_item); 
	
	OS_Return();
}

audio_menu_t audio_menu_ChangeOutputs =
{
	menu_handler_ChangeOutputs,
	am_msg_ChangeOutputs,
	0,
	NULL
};

audio_menu_t audio_menu_ChangeOutput_1 =
{
	menu_handler_ChangeOutput,
	am_msg_ChangeOutput_1,
	0,
	&audio_menu_ChangeOutputs
};

audio_menu_t audio_menu_ChangeOutput_2 =
{
	menu_handler_ChangeOutput,
	am_msg_ChangeOutput_2,
	0,
	&audio_menu_ChangeOutputs
};

audio_menu_t audio_menu_ChangeOutput_3 =
{
	menu_handler_ChangeOutput,
	am_msg_ChangeOutput_3,
	0,
	&audio_menu_ChangeOutputs
};

/* ======================= MENU CONFIG ======================= */
/* ======================= MENU CONFIG ======================= */
/* ======================= MENU CONFIG ======================= */
static void menu_handler_Config ( void )
{
	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			audio_menu = &audio_menu_Config_ChangeOutputTimeout; 
			APP.Result = AR_PLAY_MENU;
			OS_Return();
			break;

		case MH_ITEM_2:
			if ( APP.CallResult )
			{
				APP.CallResult = 0;
				APP.Result = AR_PLAY_MENU;
				OS_Return();
			}
			else
			{
				OS_Call_App(1,app_change_password);
			}
			break;

		case MH_ITEM_3:
			audio_menu = &audio_menu_Config_ChangeOutputsName; 
			APP.Result = AR_PLAY_MENU;
			OS_Return();
			break;

		default:
			audio_menu = audio_menu->menu_back;
			OS_Return();
			
	} 

	DBG("\n%s; audio_menu_Config.menu_item: %d\n",__FUNCTION__, audio_menu_Config.menu_item); 
	
}

audio_menu_t audio_menu_Config =
{
	menu_handler_Config,
	am_msg_Config,
	0,
	&audio_menu_ChangeOutputs
};

/* ============================================================================= */

/* ======================= MENU CONFIG. CHANGE OUTPUT TIMEOUT ======================= */

static void menu_handler_Config_ChangeOutputTimeout ( void )
{
	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			audio_menu = &audio_menu_Config_ChangeOutputTimeout_Unit;
			APP.Result = AR_PLAY_MENU;
			OS_Return();
			break;

		case MH_ITEM_2:
			//audio_menu = &audio_menu_Config_ChangeOutputTimeout_Timeout;
			if ( APP.CallResult )
			{
				APP.CallResult = 0;

				int timeout = StrToLong(util_enter_data_inf.data);
				if ( timeout != -1 )
				{
					DBG("\n%s; timeout: %d\n",__FUNCTION__,timeout); 
					AA_Config.output_timeout = timeout;
					AA_Config_Save();
				}
				OS_Return();
			}
			else
			{
				//util_enter_data_inf.msgs_to_play = am_msg_Config_ChangeOutputTimeout_Timeout;
				util_enter_data_inf.msg_to_play = AMSG_PLEASE_ENTER_NUMBER;
				OS_Call_App(1,util_enter_data);
			}
			break;

		default:
			audio_menu = audio_menu->menu_back;
			APP.Result = AR_PLAY_MENU;
			OS_Return();

	} 
	
}
              
audio_menu_t audio_menu_Config_ChangeOutputTimeout =
{
	menu_handler_Config_ChangeOutputTimeout,
	am_msg_Config_ChangeOutputTimeout,
	0,
	&audio_menu_Config
};

/* ========================= CHANGE OUTPUT TIMEOUT. UNIT ==================================================== */
static void menu_handler_Config_ChangeOutputTimeout_Unit ( void )
{
	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			if ( am_msg_Config_ChangeOutputTimeout_Unit[1] == AMSG_TIME_UNIT_SECOND )
			{
				am_msg_Config_ChangeOutputTimeout_Unit[1] = AMSG_TIME_UNIT_HOUR;
				AA_Config.time_unit = AA_CONFIG_TIME_UNIT_HOUR;
			}
			else
			{
				am_msg_Config_ChangeOutputTimeout_Unit[1] = AMSG_TIME_UNIT_SECOND;
				AA_Config.time_unit = AA_CONFIG_TIME_UNIT_SEC;
			}

			AA_Config_Save();
			break;

		default:
			audio_menu = audio_menu->menu_back;
			
	} 
	
	APP.Result = AR_PLAY_MENU;

	OS_Return();
}

audio_menu_t audio_menu_Config_ChangeOutputTimeout_Unit =
{
	menu_handler_Config_ChangeOutputTimeout_Unit,
	am_msg_Config_ChangeOutputTimeout_Unit,
	0,
	&audio_menu_Config_ChangeOutputTimeout
};

/* ============================================================================= */
int am_out_name;
static void menu_handler_Config_ChangeOutputsName ( void )
{
	DBG("\n%s; menu_item: %d\n",__FUNCTION__, audio_menu_Welcome.menu_item); 

	switch(audio_menu->menu_item)
	{
		case MH_ITEM_1:
			am_out_name = AMSG_OUTPUT_1_NAME;
			break;

		case MH_ITEM_2:
			am_out_name = AMSG_OUTPUT_2_NAME;
			break;

		case MH_ITEM_3:
			am_out_name = AMSG_OUTPUT_3_NAME;
			break;

	
		default:
			audio_menu = audio_menu->menu_back;
			APP.Result = AR_PLAY_MENU;
			OS_Return();
			return;
	} 

	if ( APP.CallResult )
	{
		APP.CallResult = 0;
		APP.Result = AR_PLAY_MENU;
		OS_Return();
	}
	else
	{
		util_audio_record_inf.msgs_to_play = am_msg_Config_ChangeOutputsName_Record;
		util_audio_record_inf.record_address = am_out_name;
			
		OS_Call_App(1,util_audio_record);
	}

	
}

audio_menu_t audio_menu_Config_ChangeOutputsName =
{
	menu_handler_Config_ChangeOutputsName,
	am_msg_Config_ChangeOutputsName,
	0,
	&audio_menu_Config
};

/* ============================================================================= */


static void audio_menu_Init ( void )
{
	if ( OUTP_READ(OUT_RELAY_1) )
	{
		am_msg_ChangeOutput_1[1] = AMSG_OUTPUT_STATE_ON;
	}
	else
	{
		am_msg_ChangeOutput_1[1] = AMSG_OUTPUT_STATE_OFF;
	}

	
	if ( OUTP_READ(OUT_RELAY_2) )
	{
		am_msg_ChangeOutput_2[1] = AMSG_OUTPUT_STATE_ON;
	}
	else
	{
		am_msg_ChangeOutput_2[1] = AMSG_OUTPUT_STATE_OFF;
	}

	
	if ( OUTP_READ(OUT_RELAY_3) )
	{
		am_msg_ChangeOutput_3[1] = AMSG_OUTPUT_STATE_ON;
	}
	else
	{
		am_msg_ChangeOutput_3[1] = AMSG_OUTPUT_STATE_OFF;
	}

	am_msg_Config_ChangeOutputTimeout_Timeout[1] = AA_Config.time_unit;
}


/* typedef struct _audio_menu_t */
/* { */
/* 		exe *menu_handler; */
/* 		int *menu_msg; */
/* 		int menu_item; */
/* 		struct _audio_menu_t *menu_back; */
		
/* }audio_menu_t; */


void menu_engine ( void );
void menu_engine ( void )
{
	/* if ( APP.Signal == APP_SIGNAL_CLOSE ) */
	/* { */
	/* 	DBG("\n%s; APP_SIGNAL_CLOSE\n",__FUNCTION__);  */
	/* 	APP.State = ASTE_FINISH; */
	/* } */

	switch(APP.State)
	{
		case ASTE_START:
//			DBG("\n%s; started;\n",__FUNCTION__); 
			if ( OS_Find_App(msg_play) == APP_NOT_FOUND || dtmf_digit != DTMF_EMPTY)
			{
				OS_Send_Signal(msg_play, APP_SIGNAL_CLOSE);
				APP.State = ASTE_RESET; 
			}
			break;

			
		case ASTE_RESET:	
			APP.CallResult = 0;
		  	if ( OS_Run_App(menu_play) > 0 )
			{
				APP.State = ASTE_IDLE;
			  
			}
			break;

		case ASTE_IDLE:
			if ( APP.CallResult == AR_PLAY_MENU )
			{
				APP.State = ASTE_RESET;
			}
			else
				if ( dtmf_digit != DTMF_EMPTY)
				{
					OS_Send_Signal(menu_play, APP_SIGNAL_CLOSE);
					audio_menu->menu_item = dtmf_digit;
					OS_Call_App(1,audio_menu->menu_handler);
				}
			break;

		case ASTE_FINISH:
			OS_Send_Signal(menu_play, APP_SIGNAL_CLOSE);
			OS_Return();
				
	}
}



void app_menu (void )
{
	int addr;

	/* if ( APP.Signal == APP_SIGNAL_CLOSE ) */
	/* { */
	/* 	DBG("\n%s; APP_SIGNAL_CLOSE\n",__FUNCTION__);  */
	/* 	APP.State = ASTE_FINISH; */
	/* } */
	

	switch(APP.State)
	{
		case ASTE_START:
			am_audio_on(TRUE);
			OS_SET_TIMER(60000,ASTE_BYE_BYE);
			DBG("\n%s; started;\n",__FUNCTION__); 
			APP.CallResult = 0;
			audio_menu = &audio_menu_ChangeOutputs;

			if ( incom_call_inf.phone[0] && (addr = storage.find(PHONE_LIST_0, incom_call_inf.phone)) > 0 )
			{
				DBG("\n%s; Phone: %s was found in addr: 0x%X\n",__FUNCTION__, incom_call_inf.phone, addr);
				APP.State = ASTE_MENU;
				msg_play__msg = AMSG_WELCOME;
				OS_Run_App(msg_play);
			}
			else
			{
				APP.State = ASTE_ENTER_PASSWORD;
				msg_play__msgs = am_msg_WelcomePassw;
				OS_Run_App(msgs_play);
			}
			
			//msg_play__msg = AMSG_WELCOME;
			//msg_play__msgs = NULL;
			//OS_Call_App(0,msg_play);
			break;
		
		case ASTE_ENTER_PASSWORD:
			if ( APP.CallResult )
			{
				if ( APP.CallResult == AR_SUCCSESS )
					APP.State = ASTE_MENU;
				else
					APP.State = ASTE_BYE_BYE;

				APP.CallResult = 0;
			}
			else
			{
				enter_passw_inf.addr_passw = ADDR_PASSW_1;
				OS_Call_App(1,util_enter_password);
			}
			break;


		case ASTE_MENU:
			APP.State = ASTE_IDLE;
			audio_menu_Init();
			OS_Run_App(menu_engine);

		case ASTE_IDLE:
			if ( dtmf_digit != DTMF_EMPTY)
			{
				OS_SET_TIMER(30000,ASTE_BYE_BYE);
			}
			break;

		case ASTE_BYE_BYE:
			if ( APP.CallResult )
			{
				APP.CallResult = 0;
				APP.State = ASTE_FINISH;
			}
			else
			{
				msg_play__msg = AMSG_BYE;
				OS_Call_App(1,msg_play);
			}
			break;

		case ASTE_FINISH:
			am_audio_on(FALSE);
//			OS_Kill_App(menu_engine);
			OS_Send_Signal(menu_engine, APP_SIGNAL_CLOSE);

			if ( Modem_SendCommand(1,"ATH") )
			{
				DBG("\n%s; FINISH\n",__FUNCTION__); 
				OS_Return();
			}
			
			break;
		
	}  
}
